package com.fengzhilian.timewheel.util;

import com.fengzhilian.timewheel.container.DelayQueue;
import com.fengzhilian.timewheel.runner.TaskRunner;
import com.fengzhilian.timewheel.task.TimedTask;
import com.fengzhilian.timewheel.wheel.SecondTimeWheel;
import com.fengzhilian.timewheel.wheel.TimeWheel;

import java.util.HashMap;
import java.util.Map;

/**
 * 时间轮工具类
 * @author 郭智峰
 * @Date 2019年12月25日
 */
public class TimeWheelUtil {
    private static TimeWheelUtil single = new TimeWheelUtil();
    private static Map<String, TimeWheel> timeWheelMap=new HashMap<String,TimeWheel>();
    private TimeWheelUtil() {
        //私有构造函数
    }

    public static TimeWheelUtil getInstance() {
        //静态，不用同步（类加载时已初始化，不会有多线程的问题）
        return single;
    }

    /**
     * @Title 初始化时间轮
     * @param key 时间轮标识
     * @param timeWheelType 时间轮类型标识
     *                      <p>
     *                         时间轮类型标识(timeWheelType)类型说明如下<br/>
     *                         <b> {@link TimeWheel}.TIME_WHEEL_TYPE_SIXTY_YEAR</b>
     *                         <br/>60年一甲子时间容量<br/>
     *                         <b>{@link TimeWheel}.TIME_WHEEL_TYPE_YEAR</b>
     *                         <br/>一年时间容量 <br/>
     *                         <b>{@link TimeWheel}.TIME_WHEEL_TYPE_DAY</b>
     *                         <br/>一天时间容量<br/>
     *                         <b>{@link TimeWheel}.TIME_WHEEL_TYPE_MONTH</b>
     *                         <br/>一月时间容量<br/>
     *                         <b>{@link TimeWheel}.TIME_WHEEL_TYPE_WEEK</b>
     *                         <br/>一周时间容量<br/>
     *                      </p>
     * @throws Exception 抛出异常
     */
    public  void initTimeWheel(String key,String timeWheelType) throws Exception {

        boolean result  = inTimeWheelScope(timeWheelType,TimeWheel.TIME_WHEEL_TYPE_SIXTY_YEAR,
                                      TimeWheel.TIME_WHEEL_TYPE_YEAR,
                                       TimeWheel.TIME_WHEEL_TYPE_DAY,
                                      TimeWheel.TIME_WHEEL_TYPE_MONTH,
                                      TimeWheel.TIME_WHEEL_TYPE_WEEK);
        if(!result){
            throw new Exception("\ntimeWheelType参数错误，请选择正确的时间轮类型\n" +
                    "甲子轮：TimeWheel.TIME_WHEEL_TYPE_SIXTY_YEAR\n" +
                    "年轮：TimeWheel.TIME_WHEEL_TYPE_YEAR\n" +
                    "月轮：TimeWheel.TIME_WHEEL_TYPE_MONTH\n" +
                    "周轮：TimeWheel.TIME_WHEEL_TYPE_WEEK\n" +
                    "天轮：TimeWheel.TIME_WHEEL_TYPE_DAY\n");

        } else {
            DelayQueue delayQueue = new DelayQueue();
            TimeWheel timeWheel=timeWheelMap.get(key);
            if(timeWheel==null){
                timeWheel =  new SecondTimeWheel(System.currentTimeMillis(),timeWheelType,delayQueue);
                timeWheelMap.put(key,timeWheel);
            }
            TaskRunner taskRunner = new TaskRunner(key,timeWheel,delayQueue);
            Thread thread = new Thread(taskRunner);
            thread.start();
        }


    }

    /**
     * 时间轮类型判断
     * @param timeWheel
     * @param s
     * @return
     */
    private  boolean inTimeWheelScope(String timeWheel,String... s) {
        if (timeWheel == null) {
            return false;
        }
        int len = s.length;
        if (len == 0) {
            return false;
        } else {
            for (String s1 : s
            ) {
                if(null!=s1 && timeWheel.equals(s1)){
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * 加入实践论数据
     * @param key
     * @param timedTask 加入队列
     * @throws Exception 如果超出时间轮容量则会抛出异常
     */
    public  void addTaskAndCommit(String key, TimedTask timedTask) throws Exception {
        TimeWheel timeWheel =timeWheelMap.get(key);
        if(timeWheel!=null){
            if (!timeWheel.addTask(timedTask)) {
                timedTask.excute(key);
            }
        } else {
            throw new Exception("未初始化时间轮");
        }
    }

}
